/*
 * Alan Fortes
 * 3/28/15, cpe301
 * Design assignment 4
 * The following C program varies the color of RGB LED using 
 * through the use of CTC mode to vary the color intensity
 * of the red, green, and blue lights by 10 percent increments, 
 * starting with an intensity of 10% for all colors.
 *
 * When any of the colors exceed 90% intensity, that color will
 * be reset to 10%. Whenever red exceeds 90%, green will increase
 * by 10%. Whenever green exceeds 90%, blue will increase by 10%.
 * Red is output by OC0A, green by OC1A, and blue by OC2A.
 */

//These headers allow for the pins to
//receive input and send output.
#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile int redFlipper = 1;   //These variables toggle the status of the square wave.							  
volatile int greenFlipper = 1; //If it is -1, a low output will be low, when high, the
volatile int blueFlipper = 1; //square wave will be toggled high. 
volatile int redRegVal;   //These variable store the value that will be placed in the 
volatile int greenRegVal; //OCR registers to determine the duty cycle.
volatile int blueRegVal;
volatile int timePassed1 = 0; //These 2 variables control the time that has passed by.
volatile int timePassed2 = 0;

/*
The following delay loop preserves the current color configuration
for a few milliseconds.
*/
void delayCall(void){

	while(timePassed1 < 1000){
		
		while(timePassed2 < 250){
			
			timePassed2++;
		}
		
		timePassed2 = 0;
		timePassed1++;	
	}
	
	timePassed1 = 0;
	timePassed2 = 0;
}

int main(void)
{
	int redIterations = 0; //These variables keeps track of the percentage that the
	int greenIterations = 0; //current percentage of each color, with 0 representing
	int blueIterations = 0;  //10% and 8 being 90%. When the variable reaches 9,
	                         //it will be reset to be 0 again.

    redRegVal = 230; //These variables store the value that will be placed inside
	greenRegVal = 230; //of the OCR0A, OCR1A, and OCR2A. These values represent
	blueRegVal = 230; //the time that the light will be off, as part of the duty
	                  //cycle. The on time is simply 255 - colorRegVal.
					  //Every time colorIterations is incremented, colorRegval
					  //is subtracted by 10%, 25.
    
	DDRB = 0xFF; //B port is set to output.
    DDRD = 0xFF; //D port is set to output.             
	
	OCR0A = 255 * 0.9; //The value of OCR0A, OCR1A, and OCR2A are initialized to be 
	OCR1A = 255 * 0.9; // to be 90 percent of 255.
	OCR2A = 255 * 0.9; 
    
	TCCR0A = 0x02;
    TCCR0B = 0x05; 
	TCCR1B = 0x0D; // TCNT1 is set to run under CTC mode with a prescaler of 1024.
	TCCR2A = 0x02; // TCNT2 is set to run under CTC mode with a prescaler of 1024.
	TCCR2B = 0x07; // TCNT0 is set to run under CTC mode with a prescaler of 1024.
    
    TIMSK2 |= (1 << OCIE2A);
    TIMSK1 |= (1 << OCIE1A);
    TIMSK0 |= (1 << OCIE0A); 
   
    sei(); // The interrupt enable is set to allow for interrupts to occur.
   
    while(1){ // This loop will cause the program to run indefinitely, only leaving
		
		
	
		delayCall(); //The delay is called to preserve the current value of the color.
	
		redIterations += 1; //The number of times red has increased is recorded.
						    //After each delay, the red led will 
		redRegVal -= 25; //The OCR value of the red LED is reduced by 10% to increase the duty cycle.
		
		TCNT0 = 0; //The value of the TCNT0 counter is reset.
		
		if(redIterations == 9){ //When the value of redInterations has reached 9, the 
								//value of greenIterations is increased, and the duty
								//cycle of the green LED increased by 10%.
			greenIterations += 1;
			greenRegVal -= 25;
			
			TCNT1 = 0;
			redIterations = 0; // The value of redIterations is reset, and so
			redRegVal = 230;   // is redRegVal, the value of OCR.
		}
		 
		if(greenIterations == 9){//When the value of greenInterations has reached 9, the
								 //value of greenIterations is increased, and the duty
								 //cycle of the blue LED increased by 10%.
			
			greenIterations = 0; // The value of greenIterations is reset, and so
			greenRegVal = 230;   // is greenRegVal.
			blueIterations += 1; // BlueIterations is increased.
			blueRegVal -= 25;
			TCNT2 = 0;
		}
		
		if(blueIterations == 9){ //When the value of blueIterations is increased
							     //to become 9, blueRegVal is reset and blueIterations is reset.
			blueRegVal = 230;
			blueIterations = 0;
		}
		 
	
	}         
}
//If the value of redRegVal has been reached by
//TCNT0, an interrupt occurs and the square wave
//of the red LED is toggled.
ISR(TIMER0_COMPA_vect){
   
    PORTD ^= 0x40;
    redFlipper *= -1;
   
    if(redFlipper == -1){   
	
		OCR0A = 255 - redRegVal; 
	
	}else{

		OCR0A = redRegVal; 
	}  
}
//If the value of greenRegVal has been reached by
//TCNT1, an interrupt occurs and the square wave
//of the green LED is toggled.
ISR(TIMER1_COMPA_vect){
	
	PORTB ^= 0x02;
	greenFlipper *= -1;
	
	if(greenFlipper == -1){
		
		OCR1A = 255 - greenRegVal;  
		
	}else{
				
		OCR1A = greenRegVal;  	
	}
}
//If the value of blueRegVal has been reached by
//TCNT0, an interrupt occurs and the square wave
//of the blue LED is toggled.
ISR(TIMER2_COMPA_vect){
	
	PORTB ^= 0x08;
	blueFlipper *= -1;
	
	if(blueFlipper == -1){
		  
		OCR2A = 255 - blueRegVal;  
		  
	}else{
		  
		OCR2A = blueRegVal;  
	}	
}